﻿// Copyright 2009 (c) Tom van Dijck

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Windows.Forms;

namespace Bonehead
{
    [Serializable]
    public class Profile
    {
        private DateTime mCreationDate = DateTime.Now;
        private string mOutputPath;

        // --> Needs to match profiler.h.
        public enum SampleType
        {
            Enter = 0,
            Leave = 1,
            Tail = 2,
            ManagedToUnmanagedTransition = 3,
            UnmanagedToManagedTransition = 4,
            ExceptionUnwindFunctionEnter = 5,
            ExceptionUnwindFunctionLeave = 6,
            ExceptionThrown              = 7,
        };

        public struct Sample
        {
            public SampleType Type;
            public long Thread;
            public long Function;
            public long Cycle;
        };

        public struct Method
        {
            public long Function;
            public string Name;
        };


        public Profile()
        {
        }
        
        public Profile(string aName, int aIndex)
        {
            mOutputPath = Path.GetDirectoryName(aName) + "\\" + Path.GetFileNameWithoutExtension(aName) + "_prof";
            Directory.CreateDirectory(mOutputPath);
            mOutputPath = mOutputPath + "\\prof" + aIndex.ToString();
        }

        public DateTime CreationDate
        {
            get { return mCreationDate; }
            set { mCreationDate = value; }
        }

        public string OutputPath
        {
            get { return mOutputPath; }
            set { mOutputPath = value; }
        }

        public override string ToString()
        {
            return mCreationDate.ToString();
        }

        private int strlen(byte[] aStr)
        {
            for (int i = 0; i < aStr.Length; i++)
            {
                if (aStr[i] == 0)
                {
                    return i;
                }
            }
            return aStr.Length;
        }

        [XmlIgnore]
        public IEnumerable<Method> Methods
        {
            get
            {
                Method method = new Method();
                FileStream file = new FileStream(mOutputPath + "_methods.dat", FileMode.Open, FileAccess.Read);
                using (BinaryReader reader = new BinaryReader(file))
                {
                    long length = file.Length;
                    while (file.Position < length)
                    {
                        method.Function = reader.ReadInt64();
                        byte[] str = reader.ReadBytes(512);
                        int len = strlen(str);
                        method.Name = System.Text.Encoding.ASCII.GetString(str, 0, len);
                        yield return method;
                    }
                }
            }
        }

        [XmlIgnore]
        public IEnumerable<Sample> Samples
        {
            get 
            {
                using (ProgressDialog dlg = new ProgressDialog())
                {
                    dlg.Show(Program.mMainForm);
                    Sample sample = new Sample();
                    FileStream file = new FileStream(mOutputPath + "_samples.dat", FileMode.Open, FileAccess.Read);
                    using (BinaryReader reader = new BinaryReader(file))
                    {
                        long length = file.Length;
                        dlg.SetLength(length);
                        while (file.Position < length)
                        {
                            dlg.Update(file.Position);
                            sample.Thread = reader.ReadInt64();
                            sample.Function = reader.ReadInt64();
                            sample.Cycle = reader.ReadInt64();
                            sample.Type = (SampleType)reader.ReadInt32();
                            yield return sample;
                        }
                    }
                }
            }
        }

    }
}
